
// === uuMeta.hash ===
// depend: uuMeta
/*
uuMeta.hash.pair(key, value) - return { key: value }
uuMeta.hash.size(mix) - return mix.length
uuMeta.hash.first(mix, miss) - return mix.first element
uuMeta.hash.last(mix, miss) - return mix.last element
uuMeta.hash.keys(mix) - return Array( [key1, key2, ...] )
uuMeta.hash.values(mix) - return Array( [value1, value2, ...] )
 */
(function uuMetaHashScope() {

// uuMeta.hash.pair - make one pair Hash( { key: value } )
function pair(key,     // @param String/Number: hash-key
              value) { // @param Mix: hash-value
                       // @return Hash: { key: value }
  var rv = {};

  rv[key] = value;
  return rv;
}

// uuMeta.hash.size - get hash length
function size(mix) { // @param FakeArray/Array/Hash:
                     // @return Number:
  return fn(mix, 0);
}

// uuMeta.hash.first - get first element value
function first(mix,    // @param FakeArray/Array/Hash:
               miss) { // @param Mix(= undefined): miss value
                       // @return Mix:
  return fn(mix, 1, miss);
}

// uuMeta.hash.last - get last element value
function last(mix,    // @param FakeArray/Array/Hash:
              miss) { // @param Mix(= undefined): miss value
                      // @return Mix:
  return fn(mix, 2, miss);
}

// uuMeta.hash.keys - enum index
function keys(mix) { // @param FakeArray/Array/Hash:
                     // @return Array: [key, ... ]
  return fn(mix, 3);
}

// uuMeta.hash.values - enum values
function values(mix) { // @param FakeArray/Array/Hash:
                       // @return Array: [value, ... ]
  return fn(mix, 4);
}

// inner -
function fn(mix, _kind, _miss) {
  var rv = [], ri = -1, v = _miss, i, iz, size = 0;

  if ("length" in mix) { // FakeArray / Array
    for (i = 0, iz = mix.length; i < iz; ++i) {
      if (i in mix) {
        ++size, v = mix[i];
        if (_kind === 1) {
          break;
        }
        if (_kind >= 3) {
          rv[++ri] = _kind === 3 ? i : v;
        }
      }
    }
  } else {
    for (i in mix) { // Object
      if (mix.hasOwnProperty(i)) {
        ++size, v = mix[i];
        if (_kind === 1) {
          break;
        }
        if (_kind >= 3) {
          rv[++ri] = _kind === 3 ? i : v;
        }
      }
    }
  }
  return !_kind ? size : (_kind >= 3) ? rv : v;
}

// --- initialize ---

// --- export ---
uuMeta.hash = {
  pair:   pair,
  size:   size,
  first:  first,
  last:   last,
  keys:   keys,
  values: values,
  pair:   pair
};

})(); // uuMeta.hash scope

